gtk_widget_set_opacity
gtk_widget_get_overflow
gtk_widget_set_overflow
-gtk_widget_insert_action_group
-gtk_widget_list_action_prefixes
-gtk_widget_activate_action
-gtk_widget_activate_default
gtk_widget_measure
gtk_widget_snapshot_child
gtk_widget_get_next_sibling
gtk_widget_observe_children
gtk_widget_observe_controllers
+<SUBSECTION Actions>
+gtk_widget_insert_action_group
+gtk_widget_activate_action
+gtk_widget_activate_default
+GtkWidgetActionActivateFunc
+GtkWidgetActionSetStateFunc
+GtkWidgetActionGetStateFunc
+gtk_widget_class_install_action
+gtk_widget_class_install_stateful_action
+gtk_widget_action_enabled_changed
+gtk_widget_action_state_changed
+
<SUBSECTION Standard>
GTK_WIDGET
GTK_IS_WIDGET
GtkActionMuxer *parent;
GtkWidget *widget;
+ GPtrArray *widget_actions;
+ gboolean *widget_actions_enabled;
};
G_DEFINE_TYPE_WITH_CODE (GtkActionMuxer, gtk_action_muxer, G_TYPE_OBJECT,
PROP_0,
PROP_PARENT,
PROP_WIDGET,
+ PROP_WIDGET_ACTIONS,
NUM_PROPERTIES
};
static void
gtk_action_muxer_append_group_actions (const char *prefix,
Group *group,
- GArray *actions)
+ GHashTable *actions)
{
gchar **group_actions;
gchar **action;
group_actions = g_action_group_list_actions (group->group);
for (action = group_actions; *action; action++)
{
- gchar *fullname;
-
- fullname = g_strconcat (prefix, ".", *action, NULL);
- g_array_append_val (actions, fullname);
+ char *name = g_strconcat (prefix, ".", *action, NULL);
+ g_hash_table_add (actions, name);
}
g_strfreev (group_actions);
gtk_action_muxer_list_actions (GActionGroup *action_group)
{
GtkActionMuxer *muxer = GTK_ACTION_MUXER (action_group);
- GArray *actions;
+ GHashTable *actions;
+ char **keys;
- actions = g_array_new (TRUE, FALSE, sizeof (gchar *));
+ actions = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
for ( ; muxer != NULL; muxer = muxer->parent)
{
const char *prefix;
Group *group;
+ if (muxer->widget_actions)
+ {
+ int i;
+
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ {
+ GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
+ g_hash_table_add (actions, g_strdup (action->name));
+ }
+ }
+
g_hash_table_iter_init (&iter, muxer->groups);
while (g_hash_table_iter_next (&iter, (gpointer *)&prefix, (gpointer *)&group))
gtk_action_muxer_append_group_actions (prefix, group, actions);
}
- return (gchar **)(void *) g_array_free (actions, FALSE);
+ keys = (char **)g_hash_table_get_keys_as_array (actions, NULL);
+
+ g_hash_table_steal_all (actions);
+ g_hash_table_unref (actions);
+
+ return (char **)keys;
}
static Group *
return group->group;
}
-static void
+void
gtk_action_muxer_action_enabled_changed (GtkActionMuxer *muxer,
const gchar *action_name,
gboolean enabled)
Action *action;
GSList *node;
+ if (muxer->widget_actions)
+ {
+ int i;
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ {
+ GtkWidgetAction *a = g_ptr_array_index (muxer->widget_actions, i);
+ if (strcmp (a->name, action_name) == 0)
+ {
+ muxer->widget_actions_enabled[i] = enabled;
+ break;
+ }
+ }
+ }
action = g_hash_table_lookup (muxer->observed_actions, action_name);
for (node = action ? action->watchers : NULL; node; node = node->next)
gtk_action_observer_action_enabled_changed (node->data, GTK_ACTION_OBSERVABLE (muxer), action_name, enabled);
gtk_action_muxer_action_enabled_changed (muxer, action_name, enabled);
}
-static void
+void
gtk_action_muxer_action_state_changed (GtkActionMuxer *muxer,
const gchar *action_name,
GVariant *state)
Group *group;
const gchar *unprefixed_name;
+ if (muxer->widget_actions)
+ {
+ int i;
+
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ {
+ GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
+ if (strcmp (action->name, action_name) == 0)
+ {
+ if (enabled)
+ *enabled = muxer->widget_actions_enabled[i];
+ if (parameter_type)
+ *parameter_type = action->parameter_type;
+
+ if (state_hint)
+ *state_hint = NULL;
+ if (state_type)
+ *state_type = NULL;
+ if (state)
+ *state = NULL;
+
+ if (action->get_state)
+ {
+ GVariant *s;
+
+ s = g_variant_ref_sink (action->get_state (muxer->widget, action->name));
+
+ if (state_type)
+ *state_type = g_variant_get_type (s);
+ if (state)
+ *state = g_variant_ref (s);
+
+ g_variant_unref (s);
+ }
+
+ return TRUE;
+ }
+ }
+ }
+
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
if (group)
Group *group;
const gchar *unprefixed_name;
+ if (muxer->widget_actions)
+ {
+ int i;
+
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ {
+ GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
+ if (strcmp (action->name, action_name) == 0)
+ {
+ action->activate (muxer->widget, action->name, parameter);
+
+ return;
+ }
+ }
+ }
+
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
if (group)
Group *group;
const gchar *unprefixed_name;
+ if (muxer->widget_actions)
+ {
+ int i;
+
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ {
+ GtkWidgetAction *action = g_ptr_array_index (muxer->widget_actions, i);
+ if (strcmp (action->name, action_name) == 0)
+ {
+ if (action->set_state)
+ action->set_state (muxer->widget, action->name, state);
+
+ return;
+ }
+ }
+ }
+
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
if (group)
g_value_set_object (value, muxer->widget);
break;
+ case PROP_WIDGET_ACTIONS:
+ g_value_set_boxed (value, muxer->widget_actions);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
muxer->widget = g_value_get_object (value);
break;
+ case PROP_WIDGET_ACTIONS:
+ muxer->widget_actions = g_value_get_boxed (value);
+ if (muxer->widget_actions)
+ {
+ int i;
+
+ muxer->widget_actions_enabled = g_new (gboolean, muxer->widget_actions->len);
+ for (i = 0; i < muxer->widget_actions->len; i++)
+ muxer->widget_actions_enabled[i] = TRUE;
+ }
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
+ properties[PROP_WIDGET_ACTIONS] = g_param_spec_boxed ("widget-actions", "Widget actions",
+ "Widget actions",
+ G_TYPE_PTR_ARRAY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties (class, NUM_PROPERTIES, properties);
}
/*< private >
* gtk_action_muxer_new:
* @widget: the widget to which the muxer belongs
+ * @actions: widget actions
*
* Creates a new #GtkActionMuxer.
*/
GtkActionMuxer *
-gtk_action_muxer_new (GtkWidget *widget)
+gtk_action_muxer_new (GtkWidget *widget,
+ GPtrArray *actions)
{
return g_object_new (GTK_TYPE_ACTION_MUXER,
"widget", widget,
+ "widget-actions", actions,
NULL);
}
#define GTK_IS_ACTION_MUXER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
GTK_TYPE_ACTION_MUXER))
+typedef struct {
+ char *name;
+
+ GVariantType *parameter_type;
+
+ GtkWidgetActionActivateFunc activate;
+ GtkWidgetActionSetStateFunc set_state;
+ GtkWidgetActionGetStateFunc get_state;
+} GtkWidgetAction;
+
typedef struct _GtkActionMuxer GtkActionMuxer;
GType gtk_action_muxer_get_type (void);
-GtkActionMuxer * gtk_action_muxer_new (GtkWidget *widget);
+GtkActionMuxer * gtk_action_muxer_new (GtkWidget *widget,
+ GPtrArray *actions);
void gtk_action_muxer_insert (GtkActionMuxer *muxer,
const gchar *prefix,
const gchar * gtk_action_muxer_get_primary_accel (GtkActionMuxer *muxer,
const gchar *action_and_target);
+void
+gtk_action_muxer_action_enabled_changed (GtkActionMuxer *muxer,
+ const char *action_name,
+ gboolean enabled);
+void
+gtk_action_muxer_action_state_changed (GtkActionMuxer *muxer,
+ const gchar *action_name,
+ GVariant *state);
+
+
/* No better place for these... */
gchar * gtk_print_action_and_target (const gchar *action_namespace,
const gchar *action_name,
{
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
- priv->muxer = gtk_action_muxer_new (NULL);
+ priv->muxer = gtk_action_muxer_new (NULL, NULL);
priv->accels = gtk_application_accels_new ();
}
AtkRole accessible_role;
const char *css_name;
GType layout_manager_type;
+ GPtrArray *actions;
};
enum {
gboolean create)
{
GtkActionMuxer *muxer;
+ GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (widget);
+ GtkWidgetClassPrivate *priv = widget_class->priv;
muxer = (GtkActionMuxer*)g_object_get_qdata (G_OBJECT (widget), quark_action_muxer);
if (muxer)
return muxer;
- if (create)
+ if (create || priv->actions)
{
- muxer = gtk_action_muxer_new (widget);
+ muxer = gtk_action_muxer_new (widget, priv->actions);
g_object_set_qdata_full (G_OBJECT (widget),
quark_action_muxer,
muxer,
return TRUE;
}
+/*
+ * gtk_widget_class_install_action:
+ * @widget_class: a #GtkWidgetClass
+ * @action_name: a prefixed action name, such as "clipboard.paste"
+ * @activate: callback to use when the action is activated
+ *
+ * This should be called at class initialization time to specify
+ * actions to be added for all instances of this class.
+ *
+ * Actions installed by this function are stateless. The only state
+ * they have is whether they are enabled or not. For more complicated
+ * actions, see gtk_widget_class_install_stateful_action().
+ */
+void
+gtk_widget_class_install_action (GtkWidgetClass *widget_class,
+ const char *action_name,
+ GtkWidgetActionActivateFunc activate)
+{
+ gtk_widget_class_install_stateful_action (widget_class, action_name, activate,
+ NULL, NULL, NULL);
+}
+
+/*
+ * gtk_widget_class_install_stateful_action:
+ * @widget_class: a #GtkWidgetClass
+ * @action_name: a prefixed action name, such as "clipboard.paste"
+ * @activate: callback to use when the action is activated
+ * @parameter_type: (allow-none): the parameter type, or %NULL
+ * @query: (allow-none): callback to use when the action properties
+ are queried, or %NULL for always-enabled stateless actions
+ * @query_state: (allow-none): callback to use when the action state
+ is queried, or %NULL for stateless actions
+ *
+ * This should be called at class initialization time to specify
+ * actions to be added for all instances of this class.
+ *
+ * Actions installed in this way can be simple or stateful.
+ * See the #GAction documentation for more information.
+ */
+void
+gtk_widget_class_install_stateful_action (GtkWidgetClass *widget_class,
+ const char *action_name,
+ GtkWidgetActionActivateFunc activate,
+ const char *parameter_type,
+ GtkWidgetActionSetStateFunc set_state,
+ GtkWidgetActionGetStateFunc get_state)
+{
+ GtkWidgetClassPrivate *priv = widget_class->priv;
+ GtkWidgetAction *action;
+
+ g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+
+ if (priv->actions == NULL)
+ priv->actions = g_ptr_array_new ();
+ else if (GTK_IS_WIDGET_CLASS (&widget_class->parent_class))
+ {
+ GtkWidgetClass *parent_class = GTK_WIDGET_CLASS (&widget_class->parent_class);
+ GtkWidgetClassPrivate *parent_priv = parent_class->priv;
+ GPtrArray *parent_actions = parent_priv->actions;
+
+ if (priv->actions == parent_actions)
+ {
+ int i;
+
+ priv->actions = g_ptr_array_new ();
+ for (i = 0; i < parent_actions->len; i++)
+ g_ptr_array_add (priv->actions, g_ptr_array_index (parent_actions, i));
+ }
+ }
+
+ action = g_new0 (GtkWidgetAction, 1);
+ action->name = g_strdup (action_name);
+ action->activate = activate;
+ action->parameter_type = parameter_type ? g_variant_type_new (parameter_type) : NULL;
+ action->set_state = set_state;
+ action->get_state = get_state;
+
+ GTK_NOTE(ACTIONS,
+ g_message ("%sClass: Adding %s action\n",
+ g_type_name (G_TYPE_FROM_CLASS (widget_class)),
+ action_name));
+
+ g_ptr_array_add (priv->actions, action);
+}
+
+/**
+ * gtk_widget_action_enabled_changed:
+ * @widget: a #GtkWidget
+ * @action_name: action name, such as "clipboard.paste"
+ * @enabled: whether the action is now enabled
+ *
+ * Notify when an action installed with
+ * gtk_widget_class_install_action() changes its
+ * enabled state.
+ */
+void
+gtk_widget_action_enabled_changed (GtkWidget *widget,
+ const char *action_name,
+ gboolean enabled)
+{
+ GtkActionMuxer *muxer;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ muxer = _gtk_widget_get_action_muxer (widget, TRUE);
+ gtk_action_muxer_action_enabled_changed (muxer, action_name, enabled);
+}
+
+/**
+ * gtk_widget_action_state_changed:
+ * @widget: a #GtkWidget
+ * @action_name: action name, such as "clipboard.paste"
+ * @state: the new state
+ *
+ * Notify when an action installed with
+ * gtk_widget_class_install_stateful_action() changes
+ * its state.
+ */
+void
+gtk_widget_action_state_changed (GtkWidget *widget,
+ const char *action_name,
+ GVariant *state)
+{
+ GtkActionMuxer *muxer;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ muxer = _gtk_widget_get_action_muxer (widget, TRUE);
+ gtk_action_muxer_action_state_changed (muxer, action_name, state);
+}
gboolean gtk_widget_should_layout (GtkWidget *widget);
+/**
+ * GtkWidgetActionActivateFunc:
+ * @widget: the widget to which the action belongs
+ * @action_name: the action name
+ * @parameter: parameter for activation
+ *
+ * The type of the callback functions used for activating
+ * actions installed with gtk_widget_class_install_action().
+ *
+ * The @parameter must match the @parameter_type of the action.
+ */
+typedef void (* GtkWidgetActionActivateFunc) (GtkWidget *widget,
+ const char *action_name,
+ GVariant *parameter);
+
+/**
+ * GtkWidgetActionGetStateFunc:
+ * @widget: the widget to which the action belongs
+ * @action_name: the action name
+ *
+ * The type of the callback functions used to query the state
+ * of stateful actions installed with gtk_widget_class_install_action().
+ *
+ * See the #GAction documentation for more details about the
+ * meaning of these properties.
+ */
+typedef GVariant * (* GtkWidgetActionGetStateFunc) (GtkWidget *widget,
+ const char *action_name);
+
+/**
+ * GtkWidgetActionSetStateFunc:
+ * @widget: the widget to which the action belongs
+ * @action_name: the action name
+ * @state: the new state
+ *
+ * The type of the callback functions used to change the
+ * state of actions installed with gtk_widget_class_install_action().
+ *
+ * The @state must match the @state_type of the action.
+ *
+ * This callback is used when the action state is
+ * changed via the #GActionGroup API.
+ */
+typedef void (*GtkWidgetActionSetStateFunc) (GtkWidget *widget,
+ const char *action_name,
+ GVariant *state);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_class_install_action (GtkWidgetClass *widget_class,
+ const char *action_name,
+ GtkWidgetActionActivateFunc activate);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_class_install_stateful_action (GtkWidgetClass *widget_class,
+ const char *action_name,
+ GtkWidgetActionActivateFunc activate,
+ const char *parameter_type,
+ GtkWidgetActionSetStateFunc set_state,
+ GtkWidgetActionGetStateFunc get_state);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_action_enabled_changed (GtkWidget *widget,
+ const char *action_name,
+ gboolean enabled);
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_action_state_changed (GtkWidget *widget,
+ const char *action_name,
+ GVariant *state);
+
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkWidget, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRequisition, gtk_requisition_free)